package com.think.spring;

import java.io.IOException;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.stereotype.Service;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * @description	<pre>
 * spring上下文事件驱动工具类
 *	</pre>
 * @author	dzy
 * @date	2016年8月18日
 */
@Service
@Lazy(false)
public class SpringContextHolder implements ApplicationContextAware {

	private static ApplicationContext context;

	public static ApplicationContext getApplicationContext() {
		checkApplicationContext();
		return context;
	}

	/**
	 * 从spring上下文中获取bean，通过类获取。
	 * @param clazz
	 * @return
	 */
	public static <T> T getBean(Class<T> clazz) {
		checkApplicationContext();
		return context.getBean(clazz);
	}
	
	/**
	 *从spring上下文中获取bean, 自动转型为所赋值对象的类型.
	 */
	@SuppressWarnings("unchecked")
	public static <T> T getBean(String name) {
		checkApplicationContext();
		return (T) context.getBean(name);
	}

	public void setApplicationContext(ApplicationContext ac) throws BeansException {
		context = ac;
	}

	private static void checkApplicationContext() {
		if (context == null) {
			throw new RuntimeException("applicaitonContext注解方式未注入,请在applicationContext.xml中定义SpringContextHolder");
		}
	}

	/**
	 * 获取 HttpServletRequest
	 */
	public static HttpServletRequest getHttpServletRequest() {
		checkApplicationContext();
		return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
	}
	
	/**
	 * 获取ServletContext对象
	 * @return ServletContext对象
	 */
	public static ServletContext getServletContext() {
		return ((WebApplicationContext)context).getServletContext();
	}
	
	/**
	 * 获取web.xml中定义的参数
	 * @param paramName 参数名称
	 * @return 返回配置的参数值
	 */
	public static String getInitParam(String paramName) {
		return getServletContext().getInitParameter(paramName);
	}
	
	/**
	 * 获取项目根目录真实路径
	 * @return
	 */
	public static String getRootRealPath(){
		String rootRealPath ="";
		try {
			rootRealPath=getApplicationContext().getResource("").getFile().getAbsolutePath();
		} catch (IOException e) {
			throw new RuntimeException("通过上下文获取到项目根目录绝对路径发生IO读取错误，请检查路径目录是否存在中文、空格或特殊字符");
		}
		try {
			rootRealPath=new DefaultResourceLoader().getResource("").getFile().getAbsolutePath();
		} catch (IOException e) {
			throw new RuntimeException("通过资源加载器获取到根目录绝对路径发生IO读取错误，请检查路径目录是否存在中文、空格或特殊字符");
		}
		return rootRealPath;
	}
}
